import React, { useState, useEffect } from 'react';
import { Input } from 'antd';
import type { InputProps } from 'antd';
import type { PluginCtx } from 'sula/es/types/ctx';
import type { FocusEvent, ChangeEvent, KeyboardEvent } from 'react';
import isFunction from 'lodash/isFunction';
import { history } from 'umi';

type Formatter = string | ((value: string | number) => any);

const { TextArea } = Input;
export interface Props extends Omit<InputProps, 'onChange' | 'onBlur' | 'onPressEnter'> {
  formatter?: Formatter;
  triggerEvent?: string;
  inputFormatter?: Formatter;
  outputFormatter?: Formatter;
  splitChart?: string;
  onChange?: (
    nativeEvent: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>,
    value: string,
    ctx?: PluginCtx,
  ) => void;
  onBlur?: (
    nativeEvent: FocusEvent<HTMLInputElement> | FocusEvent<HTMLTextAreaElement>,
    value: string,
    ctx?: PluginCtx,
  ) => void;
  onPressEnter?: (
    nativeEvent: KeyboardEvent<HTMLInputElement> | KeyboardEvent<HTMLTextAreaElement>,
    value: string,
    ctx?: PluginCtx,
  ) => void;
  pressEnterTriggerHistoryQueryName?: string | (() => string);
  pressEnterTriggerSubmit?: boolean;
  ctx?: PluginCtx;
}

const splitNumber = (value: string, chart = ',') => {
  const idList = value.match(/\d+/g) || [];
  return idList.join(chart);
};

const FormatterInput: React.FC<Props> = ({
  value,
  formatter = 'splitNumber',
  onChange,
  onBlur,
  onPressEnter,
  splitChart = ',',
  inputFormatter,
  outputFormatter,
  pressEnterTriggerSubmit = false,
  pressEnterTriggerHistoryQueryName,
  ...restProps
}) => {
  const { ctx = undefined, type } = restProps;
  const InputComponent = type === 'textarea' ? TextArea : Input;
  // 如果在sula插件场景，field无法通过正常途径（onChange）向上层父组件传递值更新,因此通过上下文form方法直接设置值
  const emitCtxFormValueChange = (emitValue: any) => {
    if (!ctx) {
      return;
    }
    const { form, name } = ctx;
    if (!form || !name) {
      return;
    }
    form.setFieldValue(name, emitValue);
  };
  const [formatterValue, setFormatterValue] = useState(value);

  // 方法扩展统一入口进行值初始化
  const setInitValue = (val: any) => {
    let inputValue = val;
    if (isFunction(inputFormatter)) {
      inputValue = inputFormatter(val);
    }
    setFormatterValue(inputValue);
  };

  // 方法扩展统一出口进行值不同规则的format
  const setOutputValue = (val: any) => {
    let outputValue = val;
    if (isFunction(outputFormatter)) {
      outputValue = outputFormatter(val);
    } else if (formatter === 'splitNumber') {
      outputValue = splitNumber(val, splitChart);
    }
    setFormatterValue(outputValue);
    emitCtxFormValueChange(outputValue);
    return outputValue;
  };
  useEffect(() => {
    setInitValue(value);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value]);

  const handleInputChange = (
    event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>,
  ) => {
    const originValue = event.target.value;
    setFormatterValue(originValue);
    onChange?.(event, originValue, ctx);
  };
  const handleInputBlur = (
    event: FocusEvent<HTMLInputElement> | FocusEvent<HTMLTextAreaElement>,
  ) => {
    const originValue = event.target.value;
    const outputValue = setOutputValue(originValue);
    onBlur?.(event, outputValue, ctx);
    setTimeout(() => {
      onChange?.(event, outputValue, ctx);
    }, 0);
  };
  const handlePressEnter = (
    event: KeyboardEvent<HTMLInputElement> | KeyboardEvent<HTMLTextAreaElement>,
  ) => {
    // eslint-disable-next-line
    const originValue = event.target['value'];
    const outputValue = setOutputValue(originValue);
    onPressEnter?.(event, outputValue, ctx);
    if (pressEnterTriggerSubmit && ctx && ctx.form) {
      let queryName = pressEnterTriggerHistoryQueryName || ctx.name;
      if (isFunction(pressEnterTriggerHistoryQueryName)) {
        queryName = pressEnterTriggerHistoryQueryName();
      }
      const query = { ...history.location.query, [queryName]: outputValue };
      if (outputValue === '' || outputValue === undefined) {
        delete query[queryName];
      }
      history.replace({ query });
      ctx.form.submit();
    }
  };

  return (
    <InputComponent
      {...(restProps as any)}
      value={formatterValue as any}
      onChange={(event) => {
        handleInputChange(event);
      }}
      onPressEnter={(event) => {
        handlePressEnter(event);
      }}
      onBlur={(event) => {
        handleInputBlur(event);
      }}
    />
  );
};
export default FormatterInput;
